/*
 * @Descripttion:
 * @version:
 * @Author: JinYiGao
 * @Date: 2021-08-29 15:24:15
 * @LastEditors: JinYiGao
 * @LastEditTime: 2021-08-29 15:24:15
 */
#include <utils/mesh.h>

Mesh::Mesh() {
    glCreateVertexArrays(1, &VAO);
    glCreateBuffers(1, &VBO);
    glCreateBuffers(1, &EBO);
}

Mesh::~Mesh() {}

Mesh::Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<Texture> textures) {
    this->vertices = vertices;
    this->indices = indices;
    this->textures = textures;

    // glCreateVertexArrays(1, &VAO);
    glGenVertexArrays(1, &VAO);
    glCreateBuffers(1, &VBO);
    glCreateBuffers(1, &EBO);

    setupMesh();
}

void Mesh::setupMesh() {
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glNamedBufferData(VBO, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);

    // 设置顶点格式解析
    // 调用glVertexAttribPointer() 以及glEnableVertexAttribArray() API 实现顶点数据的解析
    // 例如： glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
    //        glEnableVertexAttribArray(0);
    // 请结合shader进行顶点数据查看
    // --------------------------------------------------------------------------------
    // TODO 代码请填写在此处...
    

    // --------------------------------------------------------------------------------

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glNamedBufferData(EBO, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);

    glBindVertexArray(0);
}

// 绘制
void Mesh::Draw(Shader *shader) {
    // 各类纹理数量
    unsigned int diffuseNr = 1;
    unsigned int specularNr = 1;
    unsigned int normalNr = 1;
    unsigned int heightNr = 1;

    // 纹理绑定
    for (unsigned int i = 0; i < textures.size(); i++) {
        glActiveTexture(GL_TEXTURE0 + i); // 激活纹理
        string number;
        string name = textures[i].type;
        if (name == "texture_diffuse")
            number = std::to_string(diffuseNr++);
        else if (name == "texture_specular")
            number = std::to_string(specularNr++); // transfer unsigned int to stream
        else if (name == "texture_normal")
            number = std::to_string(normalNr++); // transfer unsigned int to stream
        else if (name == "texture_height")
            number = std::to_string(heightNr++); // transfer unsigned int to stream

        // 设置uniform纹理采样器对应的纹理id
        glUniform1i(glGetUniformLocation(shader->programId, (name + number).c_str()), i);
        // 绑定纹理
        glBindTexture(GL_TEXTURE_2D, textures[i].id);
    }

    shader->bind();
    // 绘制
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
    // glDrawArrays(GL_POINTS, 0, vertices.size());
    glBindVertexArray(0);

    glActiveTexture(GL_TEXTURE0);
}